package com.jprocms.module.cms.framework.config;

import com.jprocms.module.cms.framework.seq.IdBuilder;
import com.jprocms.module.cms.framework.seq.TableSeqDO;
import com.jprocms.module.cms.framework.seq.TableSeqService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.util.Date;

/**
 * @author jprocms
 */
@Component
@Slf4j
public class IdSeqGenerator {
    public static final int DEFAULT_STEP = 100;

    @Autowired
    private TableSeqService seqService;


    /**
     * 乐观锁+while获取主键范围
     *
     * @param tname
     * @param step
     * @param init
     * @return
     */
    @Transactional(propagation = Propagation.REQUIRES_NEW)
    public IdBuilder genarate(String tname, Integer step, Integer init) {
        if (tname == null) {
            return null;
        }
        step = step == null || step <= 0 ? DEFAULT_STEP : step;

        TableSeqDO tableSeqDO = seqService.selectByTable(tname);
        boolean isNeedUpdate = true;
        while (tableSeqDO == null) {
            TableSeqDO seqDO = new TableSeqDO();
            seqDO.settName(tname);
            seqDO.setStep(step);
            seqDO.setMaxId(step + (init == null ? 0 : init));
            seqDO.setUpdateTime(new Date());
            try {
                boolean isSuccess = seqService.save(seqDO);
                isNeedUpdate = false;
            } catch (Exception e) {
                log.error("tableSeqDO 保存失败", e);
            }
            tableSeqDO = seqService.selectByTable(tname);
        }
        while (isNeedUpdate) {
            /**
             *  乐观锁更新模式 version字段
             */
            tableSeqDO.setStep(step);
            tableSeqDO.setMaxId(step + tableSeqDO.getMaxId());
            tableSeqDO.setUpdateTime(new Date());
            isNeedUpdate = !seqService.updateByTable(tableSeqDO);
        }
        return new IdBuilder(tableSeqDO.getMaxId() - step + 1, tableSeqDO.getMaxId());
    }
}
